<template>
  <div class="container-view">
    <!-- header -->
    <div class="container-view-header">
      <!-- title -->
      <h1>附件管理</h1>
      <!-- 顶部操作栏 -->
      <div class="flex flex-wrap justify-between items-center">
        <div class="flex gap-2">
          <FormKit
            type="text"
            name="search"
            placeholder="搜索文件..."
            v-model="searchQuery"
            outer-class="!mb-0"
            input-class="w-full"
            prefix-icon="search"
            help="暂未开发"
          />
        </div>
        <div class="flex flex-wrap gap-4">
          <div class="flex flex-col justify-center">
            <div>
              TotalSize：
              <span>
                {{ formatFileSize(diskInfo.size) }}
              </span>
            </div>
            <div>
              剩余空间：
              <span>
                {{ formatFileSize(diskInfo.free) }}
              </span>
            </div>
          </div>
          <button class="btn btn-primary" @click="refreshResource">
            刷新资源
          </button>
          <button class="btn btn-primary" @click="showUploadDialog">
            上传文件
          </button>
          <DaisyDropdown
            label="选择分组"
            selected-label="分组"
            :show-value="true"
            :end="true"
            :options="groups"
            label-field="name"
            value-field="id"
            button-class="bg-base-100 hover:bg-base-200 border-base-content/20"
            @select="handleGroupChange"
          >
          </DaisyDropdown>
        </div>
      </div>
    </div>

    <!-- 文件列表 -->
    <div class="container-view-main">
      <div class="overflow-x-auto overflow-y-hidden">
        <table>
          <thead>
            <tr>
              <th class="font-medium">文件名</th>
              <th class="font-medium">类型</th>
              <th class="font-medium">大小</th>
              <th class="font-medium">上传者</th>
              <th class="font-medium">上传时间</th>
              <th class="font-medium">操作</th>
            </tr>
          </thead>
          <tbody>
            <tr class="hover" v-for="item in resourceDataSource" :key="item.id">
              <td
                class="flex justify-center items-center gap-2"
                :title="item.name"
              >
                <span
                  class="text-xl text-primary"
                  :class="
                    getFileIconClassNameByFileType(getFileTypeByMIME(item.type))
                  "
                ></span>
                <span class="max-w-48">{{ item.name }}</span>
              </td>
              <td>{{ item.type }}</td>
              <td>{{ formatFileSize(item.size) }}</td>
              <td>{{ item.uploader }}</td>
              <td>{{ formatDate(item.upload_time) }}</td>
              <td class="flex justify-center gap-2">
                <button
                  class="btn btn-sm btn-ghost text-primary"
                  @click="downloadFile(item)"
                >
                  下载
                </button>
                <button
                  class="btn btn-sm btn-ghost text-error"
                  @click="deleteFile(item.id)"
                >
                  删除
                </button>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>

    <!-- 分页控制 -->
    <div class="container-view-footer">
      <!-- 左侧显示总数 -->
      <div class="text-sm text-base-content/60">
        共 {{ resourceCount }} 条记录
      </div>

      <!-- 右侧分页控制 -->
      <div class="flex flex-wrap items-center gap-4">
        <!-- 每页条数选择 -->
        <FormKit
          type="select"
          name="pageSize"
          :options="[10, 20, 50, 100]"
          v-model="pageSize"
          outer-class="!mb-0"
          input-class="select select-bordered min-w-20"
        />

        <!-- 分页按钮组 -->
        <div class="join">
          <!-- 上一页 -->
          <button
            class="join-item btn btn-sm"
            :disabled="currentPage === 1"
            @click="currentPage > 1 ? currentPage-- : false"
          >
            <span class="iconify mdi--chevron-left"></span>
          </button>

          <!-- 页码按钮 -->
          <button
            v-for="page in displayPages"
            :key="page"
            class="join-item btn btn-sm"
            :class="{ 'btn-active': currentPage === page }"
            @click="currentPage = page"
          >
            {{ page }}
          </button>

          <!-- 下一页 -->
          <button
            class="join-item btn btn-sm"
            :disabled="currentPage === pageCount"
            @click="currentPage + 1 <= pageCount ? currentPage++ : false"
          >
            <span class="iconify mdi--chevron-right"></span>
          </button>
        </div>

        <!-- 跳转到指定页 -->
        <div class="flex items-center gap-2">
          <span class="text-sm">跳至</span>
          <FormKit
            type="number"
            name="jumpPage"
            :min="1"
            :max="pageCount"
            v-model="currentPage"
            outer-class="!mb-0"
            input-class="input input-sm input-bordered w-16 text-center"
          />
          <span class="text-sm">页</span>
        </div>
      </div>
    </div>


    <!-- 上传模态框 -->
    <DaisyDialog
      ref="uploadDialog"
      title="上传文件"
      :close-button="true"
      :content-center="false"
      @hide="handleDialogClose"
    >
      <div class="mb-4">
        <FormKit
          type="select"
          name="group"
          label="选择分组"
          :options="groupOptions"
          v-model="selectedUploadGroup"
          validation="required"
          :classes="{
            outer: 'mb-4',
            label: 'block mb-1',
            input:
              'select w-full bg-base-100 border-base-content/20 rounded focus:border-primary focus:ring-2 focus:ring-primary/20',
            message: 'text-error text-sm mt-1',
          }"
        />
      </div>

      <div>
        <!-- 文件预览区域 -->
        <div v-if="selectedUploadFileMap.size > 0" class="mb-4">
          <div class="grid grid-cols-2 gap-4">
            <div
              v-for="(file, index) in selectedUploadFileMap.values()"
              :key="index"
              class="p-4 bg-base-200 rounded-lg flex items-center gap-3"
            >
              <!-- 文件图标 -->
              <span
                class="text-2xl text-primary min-w-5"
                :class="
                  getFileIconClassNameByFileType(getFileTypeByMIME(file.type))
                "
              ></span>

              <!-- 文件信息 -->
              <div class="flex-grow min-w-0">
                <div class="truncate text-sm font-medium">{{ file.name }}</div>
                <div class="text-xs text-base-content/60">
                  {{ formatFileSize(file.size) }}
                </div>
              </div>

              <!-- 删除按钮 -->
              <button
                class="btn btn-ghost btn-sm btn-circle"
                @click="selectedUploadFileMap.delete(file.name)"
              >
                <span class="text-base-content/60 hover:text-error">✕</span>
              </button>
            </div>
          </div>
        </div>

        <!-- 拖拽上传区域 -->
        <div
          ref="uploadArea"
          class="relative p-8 border-2 border-dashed border-base-content/20 rounded-lg text-center hover:border-primary hover:bg-base-200/25 transition-colors"
          @dragover="handleDragOver"
          @dragleave="handleDragLeave"
          @drop="handleDrop"
        >
          <div class="text-base-content/60">拖拽文件到此处或者选择文件</div>
          <input
            type="file"
            name="file"
            multiple
            class="opacity-0 absolute w-full h-full top-0 left-0 cursor-pointer"
            @change="handleSelectFile"
          />
        </div>
      </div>

      <template #footer>
        <button class="btn btn-ghost" @click="closeUploadDialog">取消</button>
        <button class="btn btn-primary" @click="uploadFile">上传</button>
      </template>
    </DaisyDialog>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from "vue";
import DaisyDropdown from "@/components/daisy-dropdown/DaisyDropdown.vue";
import type { DaisyDropdownSelectArgument } from "@/components/daisy-dropdown/DaisyDropdown.vue";
import { useSimpleToast } from "@/components/simple-toast/component.plugin";
import { FormKit } from "@formkit/vue";
import { formatDate, formatFileSize } from "../util/formater";
import DaisyDialog from "@/components/daisy-dialog/DaisyDialog.vue";
import resourceAPI, {
  getResourceTypeByMIMEType,
  type Resource,
} from "@/api/resource";
import { ResponseCode, type WebResult } from "@/api/request";
import { watch } from "vue";

// 添加类型定义
interface FileGroup {
  id: number;
  name: string;
}

type FileType =
  | "text"
  | "audio"
  | "image"
  | "video"
  | "compressed"
  | "pdf"
  | "doc"
  | "xls"
  | "ppt"
  | "apk"
  | "other";
function getFileTypeByMIME(mime: string): FileType {
  const [type, subType] = mime.split("/");
  if (["text", "audio", "image", "video"].includes(type)) {
    return type as FileType;
  }
  if (
    [
      "x-compressed",
      "zip",
      "x-zip",
      "x-tar",
      "x-rar",
      "vnd.rar",
      "x-rar-compressed",
      "gzip",
      "x-gzip",
      "x-bzip",
      "x-bzip2",
      "x-7z-compressed",
      "java-archive",
    ].includes(subType)
  ) {
    return "compressed";
  }
  if (["pdf", "acrobat", "nappdf", "x-pdf"].includes(subType)) {
    return "pdf";
  }
  if (
    [
      "x-abiword",
      "msword",
      "vnd.msword",
      "x-msword",
      "vnd.openxmlformats-officedocument.wordprocessingml.document",
    ].includes(subType)
  ) {
    return "doc";
  }
  if (
    [
      "msexcel",
      "x-msexcel",
      "vnd.msexcel",
      "vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    ].includes(subType)
  ) {
    return "xls";
  }
  if (
    [
      "vnd.ms-powerpoint",
      "vnd.openxmlformats-officedocument.presentationml.presentation",
    ].includes(subType)
  ) {
    return "ppt";
  }
  if (subType === "vnd.android.package-archive") {
    return "apk";
  }
  return "other";
}
function getFileIconClassNameByFileType(type: FileType): string {
  const icons: Record<FileType, string> = {
    text: "iconify mdi--file-text",
    audio: "iconify mdi--music",
    image: "iconify mdi--image",
    video: "iconify mdi--video",
    compressed: "iconify mdi--folder-zip",
    pdf: "iconify mdi--file-pdf-box",
    doc: "iconify mdi--file-word",
    xls: "iconify mdi--file-excel",
    ppt: "iconify mdi--file-powerpoint",
    apk: "iconify mdi--android",
    other: "iconify mdi--file",
  };
  return icons[type as FileType] || icons.other;
}

// common
const toast = useSimpleToast();

// main
const diskInfo = ref({ free: 0, size: 0 });
// 分页相关状态
const pageSize = ref(10);
const currentPage = ref<any>(1);
const resourceCount = ref(0);
const resourceDataSource = ref<Resource[]>([]);
const pageCount = computed(() => {
  return Math.ceil(resourceCount.value / pageSize.value);
});
// 计算显示的页码
const displayPages = computed(() => {
  const current = currentPage.value;
  const total = pageCount.value;
  const pages: number[] = [];

  // 显示逻辑：当前页前后各显示2页，超出部分用省略号
  if (total <= 7) {
    // 总页数较少时，全部显示
    for (let i = 1; i <= total; i++) {
      pages.push(i);
    }
  } else {
    // 总是显示第一页
    pages.push(1);

    if (current <= 4) {
      // 当前页靠前
      for (let i = 2; i <= 5; i++) {
        pages.push(i);
      }
      pages.push(-1); // 用 -1 表示省略号
      pages.push(total);
    } else if (current >= total - 3) {
      // 当前页靠后
      pages.push(-1);
      for (let i = total - 4; i <= total; i++) {
        pages.push(i);
      }
    } else {
      // 当前页在中间
      pages.push(-1);
      for (let i = current - 1; i <= current + 1; i++) {
        pages.push(i);
      }
      pages.push(-1);
      pages.push(total);
    }
  }

  return pages;
});
function refreshPage(page: number = currentPage.value) {
  resourceAPI
    .getResourceCount()
    .then((result) => {
      if (result.data) {
        resourceCount.value = result.data;
      }
    });
  resourceAPI
    .getResourceByPage(page, pageSize.value)
    .then((result) => {
      if (result.data) {
        resourceDataSource.value = result.data;
      }
    });
}
refreshPage();
watch(currentPage, () => {
  refreshPage();
});
watch(pageSize, () => {
  refreshPage();
});

const searchQuery = ref("");
const groups = ref<FileGroup[]>([
  { id: 1, name: "全部" },
  { id: 2, name: "文档" },
  { id: 3, name: "图片" },
  { id: 4, name: "视频" },
  { id: 5, name: "其他" },
]);

// 上传相关
const maxFileSize = ref(0);
const maxChunkSize = ref(0);
resourceAPI.getMaxFileSize().then((result) => {
  maxFileSize.value = result.data;
});
resourceAPI.getMaxChunkSize().then((result) => {
  maxChunkSize.value = result.data;
});

const selectedUploadFileMap = ref<Map<string, File>>(new Map()); // 上传选择的
const selectedUploadGroup = ref<number | undefined>(undefined);
const uploadDialog = ref<InstanceType<typeof DaisyDialog> | null>(null);
const uploadArea = ref<HTMLDivElement | null>(null);

// FormKit
const groupOptions = computed(() => {
  return groups.value.map((group) => ({
    label: group.name,
    value: group.id,
  }));
});

// 信息相关
function refreshDiskInformation() {
  resourceAPI.getDiskInformation().then((result) => {
    if (result.data) {
      diskInfo.value = result.data;
    }
  });
}
refreshDiskInformation();

// 上传文件相关
function isSameFile(f1: File, f2: File) {
  if (f1.name === f2.name && f1.lastModified === f2.lastModified) {
    return true;
  }
  return false;
}
function addUploadFile(f: File) {
  const selected = selectedUploadFileMap.value.get(f.name);
  if (selected && isSameFile(selected, f)) {
    toast.warning(`文件${f.name}已存在`);
    return;
  }
  selectedUploadFileMap.value.set(f.name, f);
}
function addUploadFiles(files: File[] | FileList) {
  if (files instanceof FileList) {
    for (const f of files) {
      addUploadFile(f);
    }
    return;
  }
  files.forEach((f) => addUploadFile(f));
}

// 刷新资源
function refreshResource() {
  if (
    !confirm(
      "确定要刷新资源列表吗？该操作会将文件系统中不存在的资源的信息删除！",
    )
  ) {
    return;
  }
  resourceAPI.refresh().then((result) => {
    toast.info(result.message);
    toast.info("刷新页面以获取最新数据");
  });
}

// 修改打开模态框的方法
const showUploadDialog = () => {
  uploadDialog.value?.show();
};

// 修改关闭模态框的方法
const closeUploadDialog = () => {
  uploadDialog.value?.hide();
};

// 处理模态框关闭事件
const handleDialogClose = () => {
  setTimeout(() => {
    selectedUploadGroup.value = undefined;
    selectedUploadFileMap.value.clear();
  }, 100);
};

// 处理模态框拖拽离开事件
const handleDragLeave = () => {
  uploadArea.value?.classList.remove("border-primary");
  uploadArea.value?.classList.remove("bg-base-200/25");
};
// 处理模态框拖拽事件
const handleDragOver = (e: DragEvent) => {
  e.preventDefault();
  uploadArea.value?.classList.add("border-primary");
  uploadArea.value?.classList.add("bg-base-200/25");
};
// 处理模态框拖拽放置事件
const handleDrop = (e: DragEvent) => {
  e.preventDefault();
  uploadArea.value?.classList.remove("border-primary");
  uploadArea.value?.classList.remove("bg-base-200/25");
  const files = e.dataTransfer?.files;
  if (files) {
    addUploadFiles(files);
    console.log(selectedUploadFileMap.value);
  }
};
// 处理模态框选择文件事件
const handleSelectFile = (e: Event) => {
  const input = e.target as HTMLInputElement;
  const files = input.files;
  if (files) {
    addUploadFiles(files);
    console.log(selectedUploadFileMap.value);
  }
};

// 筛选分组
const handleGroupChange = (arg: DaisyDropdownSelectArgument<FileGroup>) => {
  // const groupID = arg.item.id;
  // API 调用筛选分组
  // await fetchFilesByGroup(group.id)
};

// 文件操作
function downloadFile(resource: Resource) {
  const url = `/resource/${resource.type}/${resource.uploader_id}/${resource.name}`;
  const a = document.createElement("a");
  a.href = url;
  a.download = resource.name;
  a.click();
  toast.info("下载文件" + resource.name);
}
async function deleteFile(resourceID: number) {
  if (confirm("确定要删除该文件吗？")) {
    const result = await resourceAPI.deleteResourceByID(resourceID);
    if (result.code === ResponseCode.SUCCESS) {
      toast.success("文件删除成功");
      refreshDiskInformation();
      refreshPage();
    } else {
      toast.error("文件删除失败");
    }
  }
}

async function uploadFile() {
  for (const [name, f] of selectedUploadFileMap.value.entries()) {
    toast.info(`上传文件 ${name}`);
    const resourceTpye = getResourceTypeByMIMEType(f.type);
    const hasResult = await resourceAPI.hasSelfResource(resourceTpye, name);
    if (hasResult && hasResult.data) {
      toast.warning(`文件 ${name} 已存在`);
      continue;
    }

    if (f.size > maxFileSize.value) {
      toast.warning(
        `文件 ${name} 大小超过限制（最大为 ${formatFileSize(maxFileSize.value)}）`,
      );
      continue;
    }
    const result = (await resourceAPI.uploadResource(
      {
        name,
        file: f,
      },
      (progress) => {
        toast.info(progress.toFixed(2));
      },
    )) as WebResult;
    if (result.code === ResponseCode.SUCCESS) {
      toast.success(`上传文件 ${name} 成功`);
      selectedUploadFileMap.value.delete(name);
    } else {
      toast.error(result.message.toString());
    }
  }
  refreshDiskInformation();
  refreshPage();
  closeUploadDialog();
}
</script>

